package com.lzy.cloud.sms.facade;

import com.lzy.cloud.sms.constant.RedisPrefix;
import com.lzy.cloud.sms.constant.SmsEnum;
import com.lzy.cloud.sms.constant.juhe.JuheParam;
import com.lzy.cloud.sms.dtos.MsgCodeDto;
import com.lzy.cloud.sms.dtos.SmsConfigDto;
import com.lzy.cloud.sms.dtos.SmsTemplateDto;
import com.lzy.cloud.sms.response.BaseSmsReponse;
import com.lzy.cloud.sms.response.JuheReponse;
import com.lzy.cloud.sms.request.SendSmsRequest;
import com.lzy.cloud.sms.service.MsgCodeService;
import com.lzy.framework.core.cache.cluster.RedisClusterService;
import com.lzy.framework.core.ensure.Ensure;
import com.lzy.framework.core.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Component
@PropertySource(value = "classpath:/props/jhsms.properties")
@Slf4j
public class SmsFacade {

    @Autowired
    private MsgCodeService msgCodeService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RedisClusterService redisClusterService;

    /**
     * 发送频率限制时间（秒）
     * 同一个业务  同一个手机号
     */
    @Value("${maxSecond}")
    private Integer maxSecond;
    @Value("${expireTime}")
    private Integer expireTime;


    /**
     * 发送短信
     *
     * @param sendSmsRequest
     * @return
     */
    public BaseSmsReponse smsSend(SendSmsRequest sendSmsRequest, Map<String, Object> param) {
        Ensure.that(frequencyLimit(sendSmsRequest.getAuthTarget(), sendSmsRequest.getAuthType())).isTrue("00000007");
        SmsConfigDto smsConfigDto = findSmsConfigFromRedis(sendSmsRequest.getShopWay());
        Ensure.that(smsConfigDto).isNotNull("00000003");
        Ensure.that(smsConfigDto.getStatus().equals(1)).isTrue("00000004");
        SmsEnum smsEnum = SmsEnum.findSmsShopByCode(Integer.valueOf(sendSmsRequest.getShopWay().toString()));
        switch (smsEnum) {
            case juhe:
                SmsTemplateDto smsTemplateDto = findTempFromRedis(sendSmsRequest.getAuthType());
                Ensure.that(smsTemplateDto).isNotNull("00000005");
                String sendParam = assemblyJuheParameters(smsTemplateDto, param, smsConfigDto, sendSmsRequest);
                String url = smsConfigDto.getUrl() + "?" + sendParam;
                redisClusterService.setEx(RedisPrefix.SmsTarget + sendSmsRequest.getAuthTarget() + ":" + sendSmsRequest.getAuthType(),
                        maxSecond, String.valueOf(System.currentTimeMillis()));
                return restTemplate.getForObject(url, JuheReponse.class);
            default:
                break;
        }
        return null;
    }

    /**
     * 拼接聚合接口请求参数
     *
     * @param param
     * @param sysSmsTemplate
     * @return
     */
    private String assemblyJuheParameters(SmsTemplateDto sysSmsTemplate, Map<String, Object> param, SmsConfigDto sysSmsConfigDto, SendSmsRequest request) {
        try {
            StringBuffer stringBuffer = new StringBuffer(100);
            StringBuffer tplValue = new StringBuffer(100);
            //生成验证码
            if (request.getVerification()) {
                tplValue.append(URLEncoder.encode("#code#=" + createOrUpdateCode(request), "UTF-8"));
            }
            if (sysSmsTemplate.getParams() != null && !sysSmsTemplate.getParams().equals("")) {
                String[] params = sysSmsTemplate.getParams().split(",");
                Ensure.that(params.length == param.size()).isTrue("00000006");
                for (String k : param.keySet()) {
                    for (String paramName : params) {
                        if (paramName.equals(k)) {
                            String value = "#" + k + "#=" + param.get(k).toString() + "&";
                            tplValue.append(URLEncoder.encode(value, "UTF-8"));
                        }
                    }
                }
            }
            JuheParam juheParam = (JuheParam) JsonUtils.JSONToObj(sysSmsConfigDto.getParam(), JuheParam.class);
            if (!stringBuffer.toString().equals("") && stringBuffer.toString() != null)
                stringBuffer.append("&");
            stringBuffer.append("key=").append(juheParam.getAppKey());
            stringBuffer.append("&mobile=").append(request.getAuthTarget());
            stringBuffer.append("&tpl_id=").append(sysSmsTemplate.getThirdId());
            stringBuffer.append("&tpl_value=").append(tplValue);
            log.info("短信参数:--" + stringBuffer.toString());
            return stringBuffer.toString();
        } catch (Exception e) {
            log.error("参数组装失败");
            return null;
        }
    }

    /**
     * 自动生成激活码或者验证码
     *
     * @param request
     * @return
     */
    private String createOrUpdateCode(SendSmsRequest request) {
        String code = RandomStringUtils.random(6, false, true);
        MsgCodeDto msgCodeDto = new MsgCodeDto();
        msgCodeDto.setAuthType(request.getAuthType());
        msgCodeDto.setAuthTarget(request.getAuthTarget());
        List<MsgCodeDto> msgCodeDtoList = msgCodeService.query(null, msgCodeDto);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MINUTE, expireTime);
        if (msgCodeDtoList.isEmpty()) {
            msgCodeDto.setExpiredTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime()));
            msgCodeDto.setAuthCode(code);
            Ensure.that(msgCodeService.insert(msgCodeDto)).isNotNull("00000002");
        } else {
            msgCodeDto = msgCodeDtoList.get(0);
            msgCodeDto.setStatus(0);
            msgCodeDto.setAuthCode(code);
            msgCodeDto.setExpiredTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime()));
            Ensure.that(msgCodeService.update(msgCodeDto) > 0).isTrue("00000002");
        }
        return code;
    }

    /**
     * 从redis取得配置对象
     *
     * @param id
     * @return
     */
    private SmsConfigDto findSmsConfigFromRedis(Long id) {
        return redisClusterService.get(RedisPrefix.SmsConfig + id, SmsConfigDto.class);
    }

    /**
     * 从redis取得短信模板对象
     *
     * @param id
     * @return
     */
    private SmsTemplateDto findTempFromRedis(Integer id) {
        return redisClusterService.get(RedisPrefix.SmsTemplate + id, SmsTemplateDto.class);
    }

    /**
     * 发送频率限制
     *
     * @param type
     * @param phone
     * @return
     */
    private Boolean frequencyLimit(String phone, Integer type) {
        return redisClusterService.get(RedisPrefix.SmsTarget + phone + ":" + type) == null;
    }

}
